﻿#include <QFile>
#include <assert.h>
#include <qDebug>
#include <QDomDocument>
#include <QTextStream>
#include <QDataStream>
#include <QDomNodeList>
#include <QDomElement>
#include <QDomText>
#include <QDomAttr>
#include <vtkActor.h>
#include "WindowTotalData.h"
#include "corecrt_math_defines.h"
#include "BaseModule/QJsonHelper/QJsonSerializer.h"
#include "BaseModule/GlobalHelper.h"
#include "BaseModule/IBaseSignal.h"
#include "PostProcessing/Graph2DWindowBase.h"
#include "PostProcessing/Graph3DWindowBase.h"
//#include "PostProcessing/TableChatWindow.h"
#include "PostProcessing/InfomationCurve2DBasical.h"
#include "PostProcessing/InfomationGraph3DBasical.h"


namespace DataManager
{
    // <WindowTotalData>
    WindowTotalData::~WindowTotalData()
    {
    }
    WindowTotalData* WindowTotalData::_instance = nullptr;

    WindowTotalData* WindowTotalData::getInstance()
    {
        if (_instance == nullptr)
        {
            _instance = new WindowTotalData;
        }
        return _instance;
    }

    int WindowTotalData::getLineChartWindowMaxID()
    {
        m_lineChartWindowId++;
        return m_lineChartWindowId;
    }
    int WindowTotalData::getPolarCoordinateGraphWindowMaxID()
    {
        m_polarCoordinateGraphWindowId++;
        return m_polarCoordinateGraphWindowId;
    }
    int WindowTotalData::getHeatMapWindowMaxID()
    {
        m_heatMapWindowId++;
        return m_heatMapWindowId;
    }
    int WindowTotalData::getSurfaceElectricFieldMapWindowMaxID()
    {
        m_surfaceElectricFieldMapWindowID++;
        return m_surfaceElectricFieldMapWindowID;
    }
    int WindowTotalData::getThreeDCloudMapWindowMaxID()
    {
        m_threeDCloudMapWindowID++;
        return m_threeDCloudMapWindowID;
    }
    int WindowTotalData::getThreeDSurfacePlotWindowMaxID()
    {
        m_threeDSurfacePlotWindowID++;
        return m_threeDSurfacePlotWindowID;
    }
    int WindowTotalData::getTableChatWindowMaxID()
    {
        m_tableChatWindowId++;
        return m_tableChatWindowId;
    }
    int WindowTotalData::getWindowUniversalMaxID()
    {
        m_windowUniversalMaxID++;
        m_windowUniversalIDList.append(m_windowUniversalMaxID);
        return m_windowUniversalMaxID;
    }
    void WindowTotalData::appendWindowUniversalID(int windowUniversalID)
    {
        m_windowUniversalIDList.append(windowUniversalID);
    }
    void WindowTotalData::removeWindowUniversalID(int windowUniversalID)
    {
        if (m_windowUniversalIDList.contains(windowUniversalID))
            m_windowUniversalIDList.removeOne(windowUniversalID);
    }

    int WindowTotalData::getGraph2DInformationMaxID()
    {
        m_graph2DInformationMaxID++;
        return m_graph2DInformationMaxID;
    }

    int WindowTotalData::getGraph3DInformationMaxID()
    {
        m_graph3DInformationMaxID++;
        return m_graph3DInformationMaxID;
    }

    int WindowTotalData::getThreeDCloudMapMainSettingDataMaxID()
    {
        m_threeDCloudMapMainSettingDataID++;
        return m_threeDCloudMapMainSettingDataID;
    }
    int WindowTotalData::getThreeDSurfacePlotMainSettingDataMaxID()
    {
        m_threeDSurfacePlotMainSettingDataID++;
        return m_threeDSurfacePlotMainSettingDataID;
    }
    int WindowTotalData::getSurfaceElectricFieldMapMainSettingDataMaxID()
    {
        m_surfaceElectricFieldMapMainSettingDataID++;
        return m_surfaceElectricFieldMapMainSettingDataID;
    }

    void WindowTotalData::clear()
    {
        m_lineChartWindowId = -1;
        m_polarCoordinateGraphWindowId = -1;
        m_heatMapWindowId = -1;
        m_threeDSurfacePlotWindowID = -1;
        m_threeDCloudMapWindowID = -1;
        m_surfaceElectricFieldMapWindowID = -1;
        m_tableChatWindowId = -1;
        m_windowUniversalMaxID = -1;
        m_graph2DInformationMaxID = -1;
        m_graph3DInformationMaxID = -1;
        m_threeDCloudMapMainSettingDataID = -1;
        m_threeDSurfacePlotMainSettingDataID = -1;
        m_surfaceElectricFieldMapMainSettingDataID = -1;
        m_windowUniversalIDList.clear();
        m_graph2DWindowList.clear();
        m_graph3DWindowList.clear();
        m_infomationCurve2DBasicalList.clear();
        m_infomationGraph3DBasicalList.clear();
        m_hirfExtrapolationCurvesData.clear();
        m_hirfExpElectricMergeDataFileData.clear();
    }


    void WindowTotalData::addGraph2DWindow(pst::Graph2DWindowBase* window)
    {
        m_graph2DWindowList.append(window);
        printCurrentData();     
    }
    void WindowTotalData::removeGraph2DWindow(pst::Graph2DWindowBase* window)
    {
        if (m_graph2DWindowList.contains(window))
        {
            for (auto _info2D : m_infomationCurve2DBasicalList)
            {
                if (_info2D->getGraph() == window)
                    removeInfomationCurve2DBasical(_info2D);
            }
            removeWindowUniversalID(window->getWindowUniversalID());
            m_graph2DWindowList.removeOne(window);
        }
        printCurrentData();
    }
    void WindowTotalData::removeGraph2DWindowByID(int windowID)
    {
        for (auto _2Dwindow : m_graph2DWindowList)
        {
            if (_2Dwindow->getWindowUniversalID() == windowID)
            {
                removeWindowUniversalID(_2Dwindow->getWindowUniversalID());
                m_graph2DWindowList.removeOne(_2Dwindow);
                break;
            }
        }
        printCurrentData();
    }
    pst::Graph2DWindowBase* WindowTotalData::getGraph2DWindowByID(int windowID)
    {
        for (auto _2Dwindow : m_graph2DWindowList)
        {
            if (_2Dwindow->getWindowUniversalID() == windowID)
                return _2Dwindow;
        }
        return nullptr;
    }
    pst::Graph2DWindowBase* WindowTotalData::getGraph2DWindowByUniversalID(int windowUniversalID)
    {
        for (auto _2Dwindow : m_graph2DWindowList)
        {
            if (_2Dwindow->getWindowUniversalID() == windowUniversalID)
                return _2Dwindow;
        }
        return nullptr;
    }

    void WindowTotalData::appendInfomationCurve2DBasical(pst::Info2DPointer curveInfo)
    {
        m_infomationCurve2DBasicalList.append(curveInfo);
        printCurrentData();
    }
    void WindowTotalData::removeInfomationCurve2DBasical(pst::Info2DPointer curveInfo)
    {
        if (m_infomationCurve2DBasicalList.contains(curveInfo))
        {
            m_infomationCurve2DBasicalList.removeOne(curveInfo);
            removeHirfExtrapolationCurveDataByInfo(curveInfo);
        }
        printCurrentData();
    }
    void WindowTotalData::removeInfomationCurve2DBasicalByID(int infoID)
    {
        for (auto _info : m_infomationCurve2DBasicalList)
        {
            if (_info->getInformationID() == infoID)
            {
                m_infomationCurve2DBasicalList.removeOne(_info);
                removeHirfExtrapolationCurveDataByInfo(_info);
                break;
            }
        }
        printCurrentData();
    }
    pst::Info2DPointer WindowTotalData::getInfomationCurve2DBasicalByID(int infoID)
    {
        for (auto _info : m_infomationCurve2DBasicalList)
        {
            if (_info->getInformationID() == infoID)
                return _info;
        }
        return nullptr;
    }

    void WindowTotalData::addGraph3DWindow(pst::Graph3DWindowBase* window)
    {
        m_graph3DWindowList.append(window);
        printCurrentData();
    }
    void WindowTotalData::removeGraph3DWindow(pst::Graph3DWindowBase* window)
    {
        if (m_graph3DWindowList.contains(window))
        {
            for (auto _info3D : m_infomationGraph3DBasicalList)
            {
                if (_info3D->m_graph == window)
                    removeInfomationGraph3DBasical(_info3D);
            }
            removeWindowUniversalID(window->getWindowUniversalID());
            m_graph3DWindowList.removeOne(window);
        }
        printCurrentData();
    }
    void WindowTotalData::removeGraph3DWindowByID(int windowID)
    {
        for (auto _3Dwindow : m_graph3DWindowList)
        {
            if (_3Dwindow->getWindowUniversalID() == windowID)
            {
                removeWindowUniversalID(_3Dwindow->getWindowUniversalID());
                m_graph3DWindowList.removeOne(_3Dwindow);
                break;
            }
        }
        printCurrentData();
    }
    pst::Graph3DWindowBase* WindowTotalData::getGraph3DWindowByID(int windowID)
    {
        for (auto _3Dwindow : m_graph3DWindowList)
        {
            if (_3Dwindow->getWindowUniversalID() == windowID)
                return _3Dwindow;
        }
        return nullptr;
    }
    pst::Graph3DWindowBase* WindowTotalData::getGraph3DWindowByUniversalID(int windowUniversalID)
    {
        for (auto _3Dwindow : m_graph3DWindowList)
        {
            if (_3Dwindow->getWindowUniversalID() == windowUniversalID)
                return _3Dwindow;
        }
        return nullptr;
    }

    void WindowTotalData::appendInfomationGraph3DBasical(pst::InfomationGraph3DBasical* curveInfo)
    {
        m_infomationGraph3DBasicalList.append(curveInfo);
        printCurrentData();
    }
    void WindowTotalData::removeInfomationGraph3DBasical(pst::InfomationGraph3DBasical* curveInfo)
    {
        if (m_infomationGraph3DBasicalList.contains(curveInfo))
            m_infomationGraph3DBasicalList.removeOne(curveInfo);
        printCurrentData();
    }
    void WindowTotalData::removeInfomationGraph3DBasicalByID(int infoID)
    {
        for (auto _info : m_infomationGraph3DBasicalList)
        {
            if (_info->m_informationID == infoID)
            {
                m_infomationGraph3DBasicalList.removeOne(_info);
                break;
            }
        }
        printCurrentData();
    }
    pst::InfomationGraph3DBasical* WindowTotalData::getInfomationGraph3DBasicalByID(int infoID)
    {
        for (auto _info : m_infomationGraph3DBasicalList)
        {
            if (_info->m_informationID == infoID)
                return _info;
        }
        return nullptr;
    }

    int WindowTotalData::getInfomationGraph3DBasicalIdByActor(const vtkActor* actor)
    {
        for (const auto& _info : m_infomationGraph3DBasicalList)
        {
            if (_info->m_actor == actor)
                return _info->m_informationID;
        }
        return -1;
    }


    QDomElement& WindowTotalData::writeToProjectFile(QDomDocument* doc, QDomElement* parent)
    {
        QDomElement _graphWindowDataRoot = doc->createElement("GraphWindowData");
        QDomAttr _WindowUniversalIDattr = doc->createAttribute("WindowUniversalMaxID");
        _WindowUniversalIDattr.setValue(QString::number(m_windowUniversalMaxID));
        _graphWindowDataRoot.setAttributeNode(_WindowUniversalIDattr);
        QDomAttr _lineChartWindowIDattr = doc->createAttribute("LineChartWindowMaxID");
        _lineChartWindowIDattr.setValue(QString::number(m_lineChartWindowId));
        _graphWindowDataRoot.setAttributeNode(_lineChartWindowIDattr);
        QDomAttr _polarCoordinateGraphWindowIDattr = doc->createAttribute("PolarCoordinateGraphWindowMaxID");
        _polarCoordinateGraphWindowIDattr.setValue(QString::number(m_polarCoordinateGraphWindowId));
        _graphWindowDataRoot.setAttributeNode(_polarCoordinateGraphWindowIDattr);
        QDomAttr _heatMapWindowIDattr = doc->createAttribute("HeatMapWindowMaxID");
        _heatMapWindowIDattr.setValue(QString::number(m_heatMapWindowId));
        _graphWindowDataRoot.setAttributeNode(_heatMapWindowIDattr);
        QDomAttr _threeDSurfacePlotWindowIDattr = doc->createAttribute("ThreeDSurfacePlotWindowMaxID");
        _threeDSurfacePlotWindowIDattr.setValue(QString::number(m_threeDSurfacePlotWindowID));
        _graphWindowDataRoot.setAttributeNode(_threeDSurfacePlotWindowIDattr);
        QDomAttr _threeDCloudMapWindowIDattr = doc->createAttribute("ThreeDCloudMapWindowMaxID");
        _threeDCloudMapWindowIDattr.setValue(QString::number(m_threeDCloudMapWindowID));
        _graphWindowDataRoot.setAttributeNode(_threeDCloudMapWindowIDattr);
        QDomAttr _surfaceElectricFieldMapWindowIDattr = doc->createAttribute("SurfaceElectricFieldMapWindowMaxID");
        _surfaceElectricFieldMapWindowIDattr.setValue(QString::number(m_surfaceElectricFieldMapWindowID));
        _graphWindowDataRoot.setAttributeNode(_surfaceElectricFieldMapWindowIDattr);
        QDomAttr _tableChatWindowIDattr = doc->createAttribute("TableChatWindowMaxID");
        _tableChatWindowIDattr.setValue(QString::number(m_tableChatWindowId));
        _graphWindowDataRoot.setAttributeNode(_tableChatWindowIDattr);
        QDomAttr _graph2DInformationMaxIDattr = doc->createAttribute("Graph2DInformationMaxID");
        _graph2DInformationMaxIDattr.setValue(QString::number(m_graph2DInformationMaxID));
        _graphWindowDataRoot.setAttributeNode(_graph2DInformationMaxIDattr);
        QDomAttr _graph3DInformationMaxIDattr = doc->createAttribute("Graph3DInformationMaxID");
        _graph3DInformationMaxIDattr.setValue(QString::number(m_graph3DInformationMaxID));
        _graphWindowDataRoot.setAttributeNode(_graph3DInformationMaxIDattr);

        QDomAttr _ThreeDCloudMapMainSettingDataIDattr = doc->createAttribute("ThreeDCloudMapMainSettingDataID");
        _ThreeDCloudMapMainSettingDataIDattr.setValue(QString::number(m_threeDCloudMapMainSettingDataID));
        _graphWindowDataRoot.setAttributeNode(_ThreeDCloudMapMainSettingDataIDattr);
        QDomAttr _ThreeDSurfacePlotMainSettingDataIDattr = doc->createAttribute("ThreeDSurfacePlotMainSettingDataID");
        _ThreeDSurfacePlotMainSettingDataIDattr.setValue(QString::number(m_threeDSurfacePlotMainSettingDataID));
        _graphWindowDataRoot.setAttributeNode(_ThreeDSurfacePlotMainSettingDataIDattr);
        QDomAttr _SurfaceElectricFieldMapMainSettingDataIDattr = doc->createAttribute("SurfaceElectricFieldMapMainSettingDataID");
        _SurfaceElectricFieldMapMainSettingDataIDattr.setValue(QString::number(m_surfaceElectricFieldMapMainSettingDataID));
        _graphWindowDataRoot.setAttributeNode(_SurfaceElectricFieldMapMainSettingDataIDattr);

        auto _hirfExtrapolationCurvesDataStr = GlobalHelperInstance->convertQMultiHashIntQStringToQString(m_hirfExtrapolationCurvesData);
        QDomAttr _hirfExtrapolationCurvesDataattr = doc->createAttribute("HirfExtrapolationCurvesData");
        _hirfExtrapolationCurvesDataattr.setValue(_hirfExtrapolationCurvesDataStr);
        _graphWindowDataRoot.setAttributeNode(_hirfExtrapolationCurvesDataattr);

        auto _hirfExpElectricMergeDataFileDataStr = GlobalHelperInstance->convertQMultiHashIntQStringToQString(m_hirfExpElectricMergeDataFileData);
        QDomAttr _hirfExpElectricMergeDataFileDataattr = doc->createAttribute("HirfExpElectricMergeDataFileData");
        _hirfExpElectricMergeDataFileDataattr.setValue(_hirfExpElectricMergeDataFileDataStr);
        _graphWindowDataRoot.setAttributeNode(_hirfExpElectricMergeDataFileDataattr);

        parent->appendChild(_graphWindowDataRoot);        

        //遍历m_windowUniversalIDList，到m_graph2DWindowList中找对应窗口，再写出
        for (auto _windowUniversalID : m_windowUniversalIDList)
        {
            auto _window2D = getGraph2DWindowByUniversalID(_windowUniversalID);
            if (_window2D)
            {
                _window2D->writeToProjectFile(doc, &_graphWindowDataRoot);
                continue;
            }
            auto _window3D = getGraph3DWindowByUniversalID(_windowUniversalID);
            if (_window3D)
            {
                _window3D->writeToProjectFile(doc, &_graphWindowDataRoot);
                continue;
            }
        }

        return _graphWindowDataRoot;
    }

    bool WindowTotalData::readDataFromProjectFile(QDomNodeList* nodeList)
    {
        auto _element = nodeList->at(0).toElement();
        m_windowUniversalMaxID = _element.attribute("WindowUniversalMaxID").toInt();
        m_lineChartWindowId = _element.attribute("LineChartWindowMaxID").toInt();
        m_polarCoordinateGraphWindowId = _element.attribute("PolarCoordinateGraphWindowMaxID").toInt();
        m_heatMapWindowId = _element.attribute("HeatMapWindowMaxID").toInt();
        m_threeDSurfacePlotWindowID = _element.attribute("ThreeDSurfacePlotWindowMaxID").toInt();
        m_threeDCloudMapWindowID = _element.attribute("ThreeDCloudMapWindowMaxID").toInt();
        m_surfaceElectricFieldMapWindowID = _element.attribute("SurfaceElectricFieldMapWindowMaxID").toInt();
        m_tableChatWindowId = _element.attribute("TableChatWindowMaxID").toInt();
        m_graph2DInformationMaxID = _element.attribute("Graph2DInformationMaxID").toInt();
        m_graph3DInformationMaxID = _element.attribute("Graph3DInformationMaxID").toInt();
        m_threeDCloudMapMainSettingDataID = _element.attribute("ThreeDCloudMapMainSettingDataID").toInt();
        m_threeDSurfacePlotMainSettingDataID = _element.attribute("ThreeDSurfacePlotMainSettingDataID").toInt();
        m_surfaceElectricFieldMapMainSettingDataID = _element.attribute("SurfaceElectricFieldMapMainSettingDataID").toInt();

        auto _hirfExtrapolationCurvesDataStr = _element.attribute("HirfExtrapolationCurvesData");
        m_hirfExtrapolationCurvesData = GlobalHelperInstance->convertQStringToQMultiHashIntQString(_hirfExtrapolationCurvesDataStr);
        auto _hirfExpElectricMergeDataFileDataStr = _element.attribute("HirfExpElectricMergeDataFileData");
        m_hirfExpElectricMergeDataFileData = GlobalHelperInstance->convertQStringToQMultiHashIntQString(_hirfExpElectricMergeDataFileDataStr);

        emit IBaseSignalInstance->readDataFromProjectFile(nodeList);
        return true;

    }

    void WindowTotalData::addHirfExtrapolationCurveData(pst::Info2DPointer curveInfo, QString curveName, bool isElectricMergeData)
    {
        auto _projectTreeItem = curveInfo->getProjectTreeSourceItem();
        int _itemID = -1;
        if (_projectTreeItem != nullptr)
        {
            if (!_projectTreeItem->data(Qt::UserRole + 10).isNull())
                _itemID = _projectTreeItem->data(Qt::UserRole + 10).toInt();
        }
        if (isElectricMergeData)
        {
            m_hirfExpElectricMergeDataFileData.insert(_itemID, curveName);
        }
        else
        {
            m_hirfExtrapolationCurvesData.insert(_itemID, curveName);
        }
    }
    QMultiHash<int, QString> WindowTotalData::getHirfExtrapolationCurveData()
    {
        return m_hirfExtrapolationCurvesData;
    }
    QMultiHash<int, QString> WindowTotalData::getHirfExpElectricMergeDataFileData()
    {
        return m_hirfExpElectricMergeDataFileData;
    }
    void WindowTotalData::removeHirfExtrapolationCurveData(int projectTreeItemID)
    {
        QString dirName = GlobalHelperInstance->getProjectTempIODir() + "/HirfExtrapolation";
        auto _curveNames = m_hirfExtrapolationCurvesData.values(projectTreeItemID);
        QDir _removedir(dirName);
        for (auto _curveName : _curveNames)
        {
            auto _oldFileName = _curveName + ".txt";
            _oldFileName.remove(QRegularExpression("V/m"));
            _removedir.remove(_oldFileName);
        }
        auto _fileNames = m_hirfExpElectricMergeDataFileData.values(projectTreeItemID);
        for (auto _fileName : _fileNames)
        {
            _removedir.remove(_fileName);
        }

        m_hirfExtrapolationCurvesData.remove(projectTreeItemID);
        m_hirfExpElectricMergeDataFileData.remove(projectTreeItemID);
    }
    void WindowTotalData::removeHirfExtrapolationCurveDataByInfo(pst::Info2DPointer curveInfo)
    {
        auto _projectTreeItem = curveInfo->getProjectTreeSourceItem();
        int _itemID = -1;
        if (_projectTreeItem != nullptr)
        {
            if (!_projectTreeItem->data(Qt::UserRole + 10).isNull())
                _itemID = _projectTreeItem->data(Qt::UserRole + 10).toInt();
        }
        auto _curveNames = m_hirfExtrapolationCurvesData.values(_itemID);
        if (_curveNames.count() == 2)
        {
            removeHirfExtrapolationCurveData(_itemID);
        }
    }

    void WindowTotalData::printCurrentData()
    {
        //qDebug() << "-------m_windowUniversalIDList------" << m_windowUniversalIDList.size();
        //qDebug() << "-------m_windowUniversalMaxID------" << m_windowUniversalMaxID;
        //qDebug() << "-------m_graph2DInformationMaxID------" << m_graph2DInformationMaxID;
        //qDebug() << "-------m_graph3DInformationMaxID------" << m_graph3DInformationMaxID;
        //qDebug() << "-------m_graph2DWindowList------" << m_graph2DWindowList.count();
        //qDebug() << "-------m_graph3DWindowList------" << m_graph3DWindowList.count();
        //qDebug() << "-------m_infomationCurve2DBasicalList------" << m_infomationCurve2DBasicalList.count();
        //qDebug() << "-------m_infomationGraph3DBasicalList------" << m_infomationGraph3DBasicalList.count() << "\n";

    }

}

